# server
from socket import *
import threading
import tools


CODING_TYPE = 'utf-8'

# server_addr = (tools.get_host_ip(),6000)
# server_addr = ('127.0.0.1', 6000)
server_addr = ('', 8022)
# server_addr = ('0.0.0.0', 6000)

udpSerSock = socket(AF_INET,SOCK_DGRAM)
udpSerSock.bind(server_addr)

hostDict = {}     #保存登入的客户端


def revMsg():
    global hostDict

    print(f"start rev[{server_addr}]:")
    while True:
        data, address = udpSerSock.recvfrom(1024)
        # print(data, address)
        data = data.decode(CODING_TYPE)
        try:
            print(data)
            (msg_type,msg_hostname,msg_contain)=str(data).split('|')
        except:
            print('[error msg!]', str(data))
            continue
        # 根据消息的类型作出回应
        if int(msg_type)==9:#保存连接
            msg = '%d|%s|%s' % (9,"Server","keep live")
            udpSerSock.sendto(msg.encode(CODING_TYPE), address)
        elif int(msg_type)==0:#注册客户端ip和端口
            if not msg_hostname:
                print('~~~~ hostname为空!')
            hostDict[msg_hostname]="%s:%s" % (address[0],address[1])
            print('[login: %s:%s]:%s' % (address[0],address[1],msg_hostname))
            udpSerSock.sendto(('%d|%s|%s' % (0,address[0],address[1])).encode(CODING_TYPE), address)
        elif int(msg_type)==1:#返回在线的客户端信息
            print('[query: %s]' % (msg_hostname))
            # udpSerSock.sendto('%d|%s|%s' % (1,str(hostDict)," "), address)
            msg = '%d|%s|%s' % (1,str(hostDict)," ")
            udpSerSock.sendto(msg.encode(CODING_TYPE), address)
        elif int(msg_type)==2:#p2p连接指定客户端
            online_list=hostDict.keys()
            if msg_hostname in online_list:
                item=hostDict[msg_hostname]
                (B_ip,B_port)=item.split(':')
                # print('[%s connect to :%s]' % (address[0],B_ip))
                print(f'[{address}] connect to [{B_ip}:{B_port}]')
                udpSerSock.sendto(('%d|%s|%s' % (2,B_ip,B_port)).encode(CODING_TYPE), address)
                # 通知指定客户端响应p2p连接
                print('[Remind B] --- ', data)
                udpSerSock.sendto(('%d|%s|%s' % (4,address[0],address[1])).encode(CODING_TYPE), (B_ip,int(B_port)))
            else:#指定客户端不存在
                print('[B offline] --- ', data)
                udpSerSock.sendto(('%d|%s|%s' % (3,"0","0")).encode(CODING_TYPE), address)
        elif int(msg_type)==4:
            # 清理所有的[hostDict]
            print('===== 4: 清理hostDict! =======')
            for client_name, client_address in hostDict.items():
                msg_type = -1
                msg = f'{msg_type}||'
                client_address = client_address.split(':')
                print('======== msg, client_address:', msg, type(client_address), client_address)
                udpSerSock.sendto(msg.encode(CODING_TYPE), (client_address[0], int(client_address[1])))

            hostDict = {}
            1
        else:
            raise ValueError('msg_type错误!')

def run_by_threading():
    #开始监听消息
    try:
        thread = threading.Thread(target=revMsg)
        thread.setDaemon(True)
        thread.start()
    except Exception as e:
        print("Error int start threading:", e)

    # 接受输入
    while True:
        msg = input("\n--- Enter [0] to break program...\n>>>")
        if str(msg).strip()=='0':
            print("exit!")
            break
        # udpSerSock.sendto(msg, address)
    udpSerSock.close()


def run_by_single():
    revMsg()


if __name__ == '__main__':
    try:
        run_by_threading()
        # run_by_single()
        if udpSerSock:
            udpSerSock.close()
    finally:
        print('程序已结束.')

